﻿using Core.FrameWork.Commons.Encrypt;
using Core.FrameWork.Commons.ORM.Enums;
using Microsoft.Extensions.Configuration;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Core.FrameWork.Commons.ORM.DataManager
{
    /// <summary>
    /// 数据库供应商
    /// </summary>
    public class DBServerProvider
    {
        /// <summary>
        /// 数据库配置名称
        /// </summary>
        private static string dbConfigName = Configs.DbConnectConfig.DefaultDataBase;

        /// <summary>
        /// 数据库连接
        /// </summary>
        private static IDbConnection dbConnection;


        #region Dapper Context

        /// <summary>
        /// 获取默认数据库连接
        /// </summary>
        /// <returns></returns>
        public static string GetConnectionString()
        {
            return GetConnectionString(dbConfigName);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetConnectionString(string key)
        {
            return dbConfigName = key ?? dbConfigName;
        }

        /// <summary>
        /// 获取数据库连接
        /// </summary>
        /// <param name="masterDb">是否访问主库，默认为是，否则访问从库即只读数据库</param>
        /// <returns></returns>
        public static IDbConnection GetDBConnection<TEntity>(bool masterDb = true)
        {
            DbConnectionOptions connectionOptions = GeDbConnectionOptions<TEntity>(masterDb);
            string defaultSqlConnectionString = connectionOptions.ConnectionString;
            DatabaseType dbType = connectionOptions.DatabaseType;
            if (dbType == DatabaseType.SqlServer)
                dbConnection = new SqlConnection(defaultSqlConnectionString);
            else if (dbType == DatabaseType.MySql)
                dbConnection = new MySqlConnection(defaultSqlConnectionString);
            else
                throw new NotSupportedException("The database is not supported");
            return dbConnection;
        }

        /// <summary>
        /// 获取数据库连接
        /// </summary>
        /// <param name="masterDb">是否访问主库，默认为是，否则访问从库即只读数据库</param>
        /// <returns></returns>
        public static IDbConnection GetDBConnection(bool masterDb = true)
        {
            DbConnectionOptions connectionOptions = GeDbConnectionOptions(masterDb);
            string defaultSqlConnectionString = connectionOptions.ConnectionString;
            DatabaseType dbType = connectionOptions.DatabaseType;
            if (dbType == DatabaseType.SqlServer)
                dbConnection = new SqlConnection(defaultSqlConnectionString);
            else if (dbType == DatabaseType.MySql)
                dbConnection = new MySqlConnection(defaultSqlConnectionString);
            else
                throw new NotSupportedException("The database is not supported");
            return dbConnection;
        }

        /// <summary>
        /// 获取数据库连接连接配置
        /// </summary>
        /// <typeparam name="TEntity">数据实体</typeparam>
        /// <param name="masterDb">是否访问主库，默认为是，否则访问从库即只读数据库</param>
        /// <returns></returns>
        public static DbConnectionOptions GeDbConnectionOptions<TEntity>(bool masterDb = true)
        {
            DbConnectionOptions dbConnectionOptions = new DbConnectionOptions();
            //是否需要加密
            bool conStringEncrypt = Convert.ToBoolean(Configs.DbConnectConfig.ConStringEncrypt);
            //是否需要读写分离
            bool isDBReadWriteSeparate =Convert.ToBoolean(Configs.DbConnectConfig.IsDBReadWriteSeparate);
            if (masterDb || !isDBReadWriteSeparate)
            {
                dbConnectionOptions.ConnectionString = Configs.DbConnections.DictWrite.ConnectionString;
                dbConnectionOptions.DatabaseType =  Configs.DbConnections.DictWrite.DatabaseType;
            }
            else
                dbConnectionOptions = GetReadConn(Configs.DbConnections.DictRead);
            if (conStringEncrypt)
                dbConnectionOptions.ConnectionString = DEncrypt.Decrypt(dbConnectionOptions.ConnectionString);
            return dbConnectionOptions;
        }


        /// <summary>
        /// 获取数据库连接连接配置
        /// </summary>
        /// <param name="masterDb">是否访问主库，默认为是，否则访问从库即只读数据库</param>
        /// <returns></returns>
        public static DbConnectionOptions GeDbConnectionOptions(bool masterDb = true)
        {
            DbConnectionOptions dbConnectionOptions = new DbConnectionOptions();
            //是否需要加密
            bool conStringEncrypt = Convert.ToBoolean(Configs.DbConnectConfig.ConStringEncrypt);
            //是否需要读写分离
            bool isDBReadWriteSeparate = Convert.ToBoolean(Configs.DbConnectConfig.IsDBReadWriteSeparate);
            if (masterDb || !isDBReadWriteSeparate)
            {
                dbConnectionOptions.ConnectionString = Configs.DbConnections.DictWrite.ConnectionString;
                dbConnectionOptions.DatabaseType = Configs.DbConnections.DictWrite.DatabaseType;
            }
            else
                dbConnectionOptions = GetReadConn(Configs.DbConnections.DictRead);
            if (conStringEncrypt)
                dbConnectionOptions.ConnectionString = DEncrypt.Decrypt(dbConnectionOptions.ConnectionString);
            return dbConnectionOptions;
        }

        /// <summary>
        /// 按从库数据库连接的策略进行返回连接对象，实现从库的负载均衡
        /// </summary>
        /// <param name="slaveData"></param>
        /// <returns></returns>
        private static DbConnectionOptions GetReadConn(Dictionary<string, DbConnectionOptions> slaveData)
        {
            DbConnectionOptions connectionOptions = new DbConnectionOptions();
            string queryDBStrategy = Configs.DbConnectConfig.QueryDBStrategy;
            if (queryDBStrategy == "Random")//随机策略
            {
                int index = new Random().Next(0, slaveData.Count - 1);
                connectionOptions = slaveData[index.ToString()];
            }
            else if (queryDBStrategy == "Polling")//轮询策略
            {

            }
            else //权重策略
            {

            }
            return connectionOptions;
        }
        #endregion
    }
}


